package com.wujie.mall.domain.payment.factory;

import com.wujie.mall.domain.payment.PaymentChannel;
import com.wujie.mall.domain.payment.PaymentType;
import com.wujie.mall.domain.payment.impl.AlipayChannel;
import com.wujie.mall.domain.payment.impl.BankCardChannel;
import com.wujie.mall.domain.payment.impl.WechatPayChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.List;

/**
 * 支付渠道工厂 - 工厂方法模式实现
 * 
 * 设计模式：Factory Method Pattern（工厂方法模式）
 * 应用场景：根据支付类型创建对应的支付渠道实例
 * 
 * 核心特点：
 * 1. 封装对象创建逻辑，客户端无需关心具体实现类
 * 2. 易于扩展，新增支付方式只需实现PaymentChannel接口并注册
 * 3. 运行时动态选择具体的支付渠道
 * 4. 支持支付渠道的缓存和复用
 * 
 * @author wujie
 * @since 2024-08-26
 */
@Slf4j
@Component
public class PaymentChannelFactory {

    /**
     * 支付渠道缓存，避免重复创建
     * 使用ConcurrentHashMap确保线程安全
     */
    private final Map<PaymentType, PaymentChannel> channelCache = new ConcurrentHashMap<>();

    /**
     * 所有可用的支付渠道实现
     */
    private final List<PaymentChannel> availableChannels;

    /**
     * 构造函数注入所有支付渠道实现
     * Spring会自动注入所有PaymentChannel的实现类
     */
    public PaymentChannelFactory(List<PaymentChannel> paymentChannels) {
        this.availableChannels = paymentChannels;
        initializeChannelCache();
        log.info("支付渠道工厂初始化完成，可用支付渠道: {}", availableChannels.size());
    }

    /**
     * 工厂方法：根据支付类型创建支付渠道
     * 这是工厂方法模式的核心方法
     * 
     * @param paymentType 支付类型
     * @return 支付渠道实例
     * @throws IllegalArgumentException 不支持的支付类型
     */
    public PaymentChannel createPaymentChannel(PaymentType paymentType) {
        if (paymentType == null) {
            throw new IllegalArgumentException("支付类型不能为空");
        }

        // 从缓存中获取支付渠道
        PaymentChannel channel = channelCache.get(paymentType);
        if (channel != null) {
            log.debug("从缓存获取支付渠道: {}", paymentType.getName());
            return channel;
        }

        // 如果缓存中没有，则查找可用渠道
        channel = findChannelByType(paymentType);
        if (channel != null) {
            // 添加到缓存
            channelCache.put(paymentType, channel);
            log.info("创建支付渠道成功: {}", paymentType.getName());
            return channel;
        }

        // 不支持的支付类型
        log.error("不支持的支付类型: {}", paymentType);
        throw new IllegalArgumentException("不支持的支付类型: " + paymentType.getName());
    }

    /**
     * 批量创建支付渠道
     * @param paymentTypes 支付类型列表
     * @return 支付渠道映射
     */
    public Map<PaymentType, PaymentChannel> createPaymentChannels(PaymentType... paymentTypes) {
        Map<PaymentType, PaymentChannel> channels = new ConcurrentHashMap<>();
        
        for (PaymentType type : paymentTypes) {
            try {
                PaymentChannel channel = createPaymentChannel(type);
                channels.put(type, channel);
            } catch (Exception e) {
                log.warn("创建支付渠道失败: {}, 错误: {}", type.getName(), e.getMessage());
            }
        }
        
        log.info("批量创建支付渠道完成，成功创建: {}/{}", channels.size(), paymentTypes.length);
        return channels;
    }

    /**
     * 获取所有支持的支付类型
     * @return 支持的支付类型列表
     */
    public List<PaymentType> getSupportedPaymentTypes() {
        return availableChannels.stream()
                .map(PaymentChannel::getPaymentType)
                .distinct()
                .toList();
    }

    /**
     * 检查是否支持指定的支付类型
     * @param paymentType 支付类型
     * @return true-支持，false-不支持
     */
    public boolean isPaymentTypeSupported(PaymentType paymentType) {
        return channelCache.containsKey(paymentType) || 
               availableChannels.stream().anyMatch(channel -> channel.supports(paymentType));
    }

    /**
     * 获取支付渠道详细信息
     * @return 支付渠道信息映射
     */
    public Map<String, Object> getChannelInfo() {
        Map<String, Object> info = new ConcurrentHashMap<>();
        info.put("total_channels", availableChannels.size());
        info.put("cached_channels", channelCache.size());
        info.put("supported_types", getSupportedPaymentTypes().stream()
                .map(PaymentType::getName)
                .toList());
        return info;
    }

    /**
     * 清空支付渠道缓存
     * 主要用于测试或重新加载配置
     */
    public void clearCache() {
        channelCache.clear();
        log.info("支付渠道缓存已清空");
    }

    /**
     * 重新初始化支付渠道缓存
     */
    public void refreshCache() {
        clearCache();
        initializeChannelCache();
        log.info("支付渠道缓存已刷新");
    }

    /**
     * 初始化支付渠道缓存
     */
    private void initializeChannelCache() {
        for (PaymentChannel channel : availableChannels) {
            PaymentType type = channel.getPaymentType();
            channelCache.put(type, channel);
            log.debug("注册支付渠道: {} -> {}", type.getName(), channel.getClass().getSimpleName());
        }
    }

    /**
     * 根据支付类型查找支付渠道
     * @param paymentType 支付类型
     * @return 支付渠道实例，如果找不到则返回null
     */
    private PaymentChannel findChannelByType(PaymentType paymentType) {
        return availableChannels.stream()
                .filter(channel -> channel.supports(paymentType))
                .findFirst()
                .orElse(null);
    }

    /**
     * 获取工厂统计信息
     * @return 统计信息
     */
    public String getFactoryStats() {
        return String.format("PaymentChannelFactory{可用渠道=%d, 缓存渠道=%d, 支持类型=%s}", 
                           availableChannels.size(), 
                           channelCache.size(),
                           getSupportedPaymentTypes().stream()
                                   .map(PaymentType::getCode)
                                   .reduce((a, b) -> a + "," + b)
                                   .orElse("none"));
    }

    @Override
    public String toString() {
        return getFactoryStats();
    }
}